Python 使用 ElementTree 寫入 XML 格式檔案與縮排


Posted by 小江 on 2022-11-17

目標產出

Output.xml

<EDC>
  <object_id>OBJ_ID</object_id>
  <product_id>PROD_ID</product_id>
  <eqp_id>EQP_ID</eqp_id>
  <owner></owner>
  <recipe_id>RECIPE_ID</recipe_id>
  <operation>OPER</operation>
  <cldate>2022-11-16</cldate>
  <cltime>23:25:39</cltime>
  <datas>
    <iary>
      <item_name>illuminance_B_NA</item_name>
      <item_type>X</item_type>
      <item_value>751</item_value>
    </iary>
    <iary>
      <item_name>illuminance_B_PL</item_name>
      <item_type>X</item_type>
      <item_value>2233</item_value>
    </iary>
    <iary>
      <item_name>illuminance_U_NA</item_name>
      <item_type>X</item_type>
      <item_value>623</item_value>
    </iary>
    <iary>
      <item_name>illuminance_U_PL</item_name>
      <item_type>X</item_type>
      <item_value>2123</item_value>
    </iary>
  </datas>
</EDC>

程式說明

基本ElementTree 操作

import xml.etree.ElementTree as ET

XML = ET.ElementTree()  # 建立 ElementTree 物件
EDC = ET.Element('EDC')  # 建立 Element 物件
XML._setroot(EDC)   # 設定ElementTree XML 的根節點為EDC

_object_id = ET.SubElement(EDC, 'object_id')  # 建立 SubElement 物件 - object_id

# print(ET.dump(XML))  # print Element / ElementTree 內容
XML.write("Output.xml")  # 輸出檔案

output.xml

<EDC><object_id /></EDC>

write() parameter - short_empty_elements

XML.write("Output.xml") → XML.write("Output.xml", short_empty_elements=False)

output.xml

<EDC><object_id></object_id></EDC>

換行與縮排 - pretty_xml

import xml.etree.ElementTree as ET
def pretty_xml(element, indent, newline, level=0):
  if element:  # 判断element是否有子元素
      if (element.text is None) or element.text.isspace():  # 如果element的text没有内容
          element.text = newline + indent * (level + 1)
      else:
          element.text = newline + indent * \
              (level + 1) + element.text.strip() + \
              newline + indent * (level + 1)
          # else:  # 此处两行如果把注释去掉,Element的text也会另起一行
          # element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
  temp = list(element)  # 将element转成list
  for subelement in temp:
      # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
      if temp.index(subelement) < (len(temp) - 1):
          subelement.tail = newline + indent * (level + 1)
      else:  # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
          subelement.tail = newline + indent * level
      pretty_xml(subelement, indent, newline,
                  level=level + 1)  # 对子元素进行递归操作
  return element

XML = ET.ElementTree()  # 建立 ElementTree 物件
EDC = ET.Element('EDC')  # 建立 Element 物件
XML._setroot(EDC)   # 設定ElementTree XML 的根節點為EDC

_object_id = ET.SubElement(EDC, 'object_id')  # 建立 SubElement 物件 - object_id

# 對root Element 進行縮排與換行
EDC = pretty_xml(EDC, "  ", "\n") # 縮排使用兩個空格
# EDC = pretty_xml(EDC, "\t", "\n")  # 縮排使用 tab

XML.write("Output.xml", short_empty_elements=False)  # 輸出檔案

output.xml

<EDC>
  <object_id></object_id>
</EDC>

完整程式碼

import xml.etree.ElementTree as ET
import traceback
import datetime


def item2XML(xml_filename, object_id, product_id, eqp_id, owner, recipe_id, operation, cldate, cltime, datas):
    # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行
    def pretty_xml(element, indent, newline, level=0):
        if element:  # 判断element是否有子元素
            if (element.text is None) or element.text.isspace():  # 如果element的text没有内容
                element.text = newline + indent * (level + 1)
            else:
                element.text = newline + indent * \
                    (level + 1) + element.text.strip() + \
                    newline + indent * (level + 1)
                # else:  # 此处两行如果把注释去掉,Element的text也会另起一行
                # element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
        temp = list(element)  # 将element转成list
        for subelement in temp:
            # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
            if temp.index(subelement) < (len(temp) - 1):
                subelement.tail = newline + indent * (level + 1)
            else:  # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
                subelement.tail = newline + indent * level
            pretty_xml(subelement, indent, newline,
                       level=level + 1)  # 对子元素进行递归操作
        return element
    try:
        XML = ET.ElementTree()  # 建立 ElementTree 物件
        EDC = ET.Element('EDC')  # 建立 Element 物件
        XML._setroot(EDC)   # 設定ElementTree XML 的根節點為EDC

        _object_id = ET.SubElement(EDC, 'object_id')
        _object_id.text = object_id

        _product_id = ET.SubElement(EDC, 'product_id')
        _product_id.text = product_id

        _eqp_id = ET.SubElement(EDC, 'eqp_id')
        _eqp_id.text = eqp_id

        _owner = ET.SubElement(EDC, 'owner')
        _product_id.text = product_id

        _recipe_id = ET.SubElement(EDC, 'recipe_id')
        _recipe_id.text = recipe_id

        _operation = ET.SubElement(EDC, 'operation')
        _operation.text = operation

        _cldate = ET.SubElement(EDC, 'cldate')
        _cldate.text = cldate

        _cltime = ET.SubElement(EDC, 'cltime')
        _cltime.text = cltime

        _datas = ET.SubElement(EDC, 'datas')
        for data in datas:
            _iary = ET.SubElement(_datas, 'iary')

            _item_name = ET.SubElement(_iary, 'item_name')
            _item_name.text = data['item_name']

            _item_type = ET.SubElement(_iary, 'item_type')
            _item_type.text = data['item_type']

            _item_value = ET.SubElement(_iary, 'item_value')
            _item_value.text = str(data['item_value'])
        EDC = pretty_xml(EDC, "  ", "\n")
        XML.write(xml_filename,
                  short_empty_elements=False)  # 寫入檔案
        return True
    except Exception:
        print(traceback.format_exc())
        return False


if __name__ == "__main__":
    object_id = "OBJ_ID"
    product_id = "PROD_ID"
    eqp_id = "EQP_ID"
    owner = "OWNER"
    recipe_id = "RECIPE_ID"
    operation = "OPER"
    cldate = datetime.datetime.now().strftime("%Y-%m-%d")
    cltime = datetime.datetime.now().strftime("%H:%M:%S")
    datas = [
        {"item_name": "illuminance_B_NA", "item_type": "X", "item_value": 751},
        {"item_name": "illuminance_B_PL", "item_type": "X", "item_value": 2233},
        {"item_name": "illuminance_U_NA", "item_type": "X", "item_value": 623},
        {"item_name": "illuminance_U_PL", "item_type": "X", "item_value": 2123},
    ]
    result = item2XML("Output.xml", object_id, product_id, eqp_id,
                      owner, recipe_id, operation, cldate, cltime, datas)
    print(f"IsSuccess: {result}")

參考文獻

  1. Python使用ElementTree处理XML缩进和换行
  2. The ElementTree XML API

#Python #xml







Related Posts

How to compare a fixed date stored in an object with the current date in JavaScript?

How to compare a fixed date stored in an object with the current date in JavaScript?

Contextual Data Augmentation

Contextual Data Augmentation

發生在 GitHub conflict 的衝突——無法發 PR 合併分支

發生在 GitHub conflict 的衝突——無法發 PR 合併分支


Comments